package gipfProject.games.zertz.data;

public class Location {

	public int x, y;

	public Location(int startX, int startY) {
		x = startX;
		y = startY;
	}

	/**
	 * Usage is this.directionOffset(this.directionTo(otherLocation))
	 * 
	 * Visually:
	 * 
	 * 4 2 6 0 3 5 1
	 * 
	 * Private, as this should be invoked via moveDirection()
	 * 
	 * @param direction
	 * @return the coordinates for the tile in that direction
	 */

	private Location directionOffset(int direction) {

		switch (direction) {
		case 4:
			return new Location(0, 2); // Straight Up
		case 6:
			return new Location(-1, -1);
		case 5:
			return new Location(-1, 1);
		case 1:
			return new Location(0, -2); // Straight Down
		case 3:
			return new Location(1, 1);
		case 2:
			return new Location(1, -1);
		default:
			return new Location(0, 0);
		}
	}

	/**
	 * Returns the direction from this location -> inputLocation -2 =
	 * Non-Cardinal -1 = Horizontal (invalid) 0 = No movement
	 * 
	 * 1 = Straight Up 2 = Left Up 3 = Left Down 4 = Straight Down 5 = Right
	 * Down 6 = Right Up
	 * 
	 * Visually:
	 * 
	 * 1 6 2 0 5 3 4
	 * 
	 */

	public int directionTo(Location inputLocation) {

		// Calculate the difference in the X & Y coordinates
		int diffX = this.x - inputLocation.x;
		int diffY = this.y - inputLocation.y;

		int absDiffX = Math.abs(diffX);
		int absDiffY = Math.abs(diffY);

		// No movement
		if (absDiffY == 0 && diffX == 0) {
			return 0;
		}

		// Horizontal movement
		if (absDiffY == 0) {
			return -1;
		}

		// Vertical movement
		if (diffX == 0) {
			if (diffY > 0) {
				return 1;
			} // Straight up
			else {
				return 4;
			} // Straight down
		}

		// Diagonal movement
		if (absDiffX == absDiffY) {
			if (diffY > 0 && diffX < 0) {
				return 2;
			} // Upper-left

			if (diffY < 0 && diffX < 0) {
				return 3;
			} // Lower-left

			if (diffY < 0 && diffX > 0) {
				return 5;
			} // Lower-right

			if (diffY > 0 && diffX > 0) {
				return 6;
			} // Upper-right
		}

		// Not a hex-cardinal motion
		return -2;
	}

	public boolean validDirection(Location inputLocation) {
		if (this.directionTo(inputLocation) >= 0) {
			return true;
		} else {
			return false;
		}
	}

	public int distanceTo(Location inputLocation) {
		int sumDiff;

		int absDiffX = Math.abs(this.x - inputLocation.x);
		int absDiffY = Math.abs(this.y - inputLocation.y);

		// The distance is either the diagonal distance...
		sumDiff = (absDiffX + absDiffY) / 2;

		// ...Or the movement on the X-axis
		sumDiff = Math.max(sumDiff, absDiffX);

		return sumDiff;
	}

	public Location move(int moveX, int moveY) {
		Location newLocation;
		newLocation = new Location(this.x + moveX, this.y + moveY);

		return newLocation;
	}

	public Location moveDirection(int direction, int distance) {
		Location newLocation = new Location(this.x, this.y);

		int moveX = directionOffset(direction).x;
		int moveY = directionOffset(direction).y;

		for (int i = 0; i < distance; i++) {
			newLocation = newLocation.move(moveX, moveY);
		}

		return newLocation;
	}
}
